home *** CD-ROM | disk | FTP | other *** search
- program split ;
-
- {-----------------------------------------------------------------------------}
- { SPLIT -- utility to split text files into smaller chunks }
- { syntax: SPLIT <filename> [<chunksize>[k|l]] }
- { chunksize can be given as number of bytes, kilobytes or in lines }
- { file name of chunks is same as input file }
- { file extension of chunks is '.000', '.001', '.002' etc. }
- { program tries to split at end of line (unless line longer than chunk size) }
- {-----------------------------------------------------------------------------}
-
- {$M 16348,65535,65535}
- {$B-}
- {$I-}
-
- uses Crt,Dos ;
-
- const Version = '1.04' ;
- Date = '1 Mar 1992' ;
- DefaultChunkSize = 60000 ;
- BufSize = 65536 - 512 ;
-
- type Buf = array[1..BufSize] of char ;
-
- var InFile, OutFile : file ;
- InFileName, OutFileName : PathStr ;
- SizeInLines : boolean ; { chunk size given as no. of lines? }
- DiskError : word ;
- ChunkSize, ChunkNr : longint ;
- ChunkSizeStr : string ; { string representation of ChunkSize }
- ChunkNrStr : string[3] ; { string representation of ChunkNr }
- code : integer ; { result of string->number conversion }
- BufPtr : ^Buf ;
- FileDir : DirStr ; { directory part of InFileName }
- FileName : NameStr ; { file name part of InFileName }
- FileExt : ExtStr ; { file extension part of InFileName }
- Ready : boolean ;
- ChunkFull : boolean ;
- Answer : char ; { overwrite existing output file? }
- BytesRead,BytesToWrite,BytesWritten : word ;
- LineCounter : longint ;
- i : word ;
- LF,EF : char ;
-
- {-----------------------------------------------------------------------------}
- { Indicates whether a filename contains wildcard characters }
- {-----------------------------------------------------------------------------}
-
- function Wildcarded (Name : PathStr) : boolean ;
-
- begin
- Wildcarded := (Pos('*',Name) <> 0) or (Pos('?',Name) <> 0) ;
- end ;
-
- {-----------------------------------------------------------------------------}
- { Returns True if the file <FileName> exists, False otherwise. }
- {-----------------------------------------------------------------------------}
-
- function Exists (FileName : PathStr) : boolean ;
-
- var SR : SearchRec ;
-
- begin
- FindFirst (FileName,ReadOnly + Hidden + SysFile,SR) ;
- Exists := (DosError = 0) and (not Wildcarded(Filename)) ;
- end ;
-
- {-----------------------------------------------------------------------------}
- { Reads the result of the last I/O operation into the DiskError variable }
- { and produces an error message if an error has occurred. }
- {-----------------------------------------------------------------------------}
-
- procedure CheckDiskError ;
-
- var ErrorText : string ;
-
- begin
- DiskError := IOResult ;
- if DiskError <> 0
- then begin
- case DiskError of
- 2 : ErrorText := 'File not found' ;
- 3 : ErrorText := 'Path not found' ;
- 5 : ErrorText := 'File access denied' ;
- 101 : ErrorText := 'Disk write error' ;
- 150 : ErrorText := 'Disk is write-protected' ;
- 152 : ErrorText := 'Drive not ready' ;
- 159 : ErrorText := 'Printer out of paper' ;
- 160 : ErrorText := 'Device write fault' ;
- else begin
- Str (DiskError,ErrorText) ;
- ErrorText := 'I/O error ' + ErrorText ;
- end ;
- end ; { of case }
- Writeln ;
- Writeln (ErrorText) ;
- end ; { of if }
- end ;
-
- {-----------------------------------------------------------------------------}
-
- begin
- LF := #10 ; { line-feed character }
- EF := #26 ; { end-of-file-character }
- Writeln ('SPLIT -- utility to split text files into smaller chunks') ;
- Writeln (' version ',Version,' ',Date) ;
- Writeln ;
- if (ParamCount < 1) or (ParamCount > 2)
- then begin
- { wrong number of parameters: give help then quit program }
- Writeln ('Usage: SPLIT <filename> [<chunksize> [k|l]]') ;
- Exit ; { not nice programming but to prevent huge nesting of ifs }
- end ;
- if ParamCount = 1
- then begin
- { no chunk size given: use default }
- SizeInLines := false ;
- ChunkSize := DefaultChunkSize ;
- end
- else begin
- ChunkSizeStr := ParamStr(2) ;
- if UpCase(ChunkSizeStr[Length(ChunkSizeStr)]) = 'L'
- then begin
- { chunk size given in lines }
- SizeInLines := true ;
- Val (Copy(ChunkSizeStr,1,Length(ChunkSizeStr)-1),
- ChunkSize,code) ;
- end
- else begin
- SizeInLines := false ;
- if UpCase(ChunkSizeStr[Length(ChunkSizeStr)]) = 'K'
- then begin
- { chunk size given in kilobytes }
- Val (Copy(ChunkSizeStr,1,Length(ChunkSizeStr)-1),
- ChunkSize,code) ;
- ChunkSize := ChunkSize * 1024 ;
- end
- else { chunk size given in bytes }
- Val (ChunkSizeStr,ChunkSize,code) ;
- { decrease ChunkSize by 1 to allow for EOF char }
- Dec (ChunkSize) ;
- end ;
- if (code <> 0) or (ChunkSize <= 0)
- then begin
- Writeln ('Invalid chunk size "',ParamStr(2),'"') ;
- Writeln ('Usage: SPLIT <filename> [<chunksize>[k|l]]') ;
- Exit ;
- end ;
- end ;
- InFileName := FExpand (ParamStr(1)) ;
- if not Exists(InFileName)
- then begin
- Writeln ('Input file "',InFileName,'" not found') ;
- Exit ;
- end
- else Writeln ('Splitting file "',InFileName,'"') ;
- Assign (InFile,InFileName) ;
- Reset (InFile,1) ;
- CheckDiskError ;
- { allocate memory buffer for contents of file }
- GetMem (BufPtr,BufSize) ;
- ChunkNr := 0 ;
- FSplit (InFileName,FileDir,FileName,FileExt) ;
- Ready := (DiskError <> 0) ;
- ChunkFull := true ;
- while not Ready do
- begin
- if ChunkFull
- then begin
- { start writing new chunk: }
- { construct output file name }
- Str (ChunkNr,ChunkNrStr) ;
- while Length(ChunkNrStr) < 3 do
- ChunkNrStr := '0' + ChunkNrStr ;
- OutFileName := FExpand (FileName + '.' + ChunkNrStr) ;
- if Exists (OutFileName)
- then begin
- Write ('File "',OutFileName,'" already exists. ') ;
- Write ('Skip, Overwrite, Abort? (S/O/A) ') ;
- repeat Answer := UpCase(ReadKey) ;
- until Answer in ['S','O','A'] ;
- Writeln (Answer) ;
- end
- else Answer := 'O' ;
- case Answer of
- 'S' : { skip }
- Inc (ChunkNr) ;
- 'O' : begin
- { open output file }
- Write ('File "',OutFileName,'" ... ') ;
- Assign (OutFile,OutFileName) ;
- ReWrite (OutFile,1) ;
- CheckDiskError ;
- ChunkFull := (DiskError <> 0) ;
- LineCounter := 1 ;
- end ;
- 'A' : { abort }
- Ready := True ;
- end ; { of case }
- end ; { of if }
- if not ChunkFull
- then begin
- { write chunk }
- repeat BlockRead (InFile,BufPtr^,BufSize,BytesRead) ;
- CheckDiskError ;
- if (BytesRead = 0) or (DiskError <> 0)
- then Ready := true
- else begin
- BytesToWrite := BytesRead ;
- { scan block and check if chunk is full }
- i := 0 ;
- repeat
- Inc(i) ;
- if BufPtr^[i] = LF
- then begin
- Inc (LineCounter) ;
- if SizeInLines
- then begin
- ChunkFull := (LineCounter >
- ChunkSize) ;
- BytesToWrite := i ;
- end
- else if (FileSize(OutFile)+i) <=
- ChunkSize
- then BytesToWrite := i
- else begin
- ChunkFull := true ;
- Dec (LineCounter) ;
- end ;
- end ;
- until ChunkFull or (i = BytesRead) ;
- { to make sure last line is also written: }
- if (not SizeInLines) and
- ((FileSize(OutFile)+BytesRead) < ChunkSize)
- then BytesToWrite := BytesRead ;
- { write bytes to output file }
- BlockWrite (OutFile,BufPtr^,BytesToWrite,
- BytesWritten) ;
- { correct current position of input file }
- Seek (InFile,FilePos(InFile)-
- (BytesRead-BytesWritten)) ;
- if (not SizeInLines) and
- (FileSize(OutFile) >= ChunkSize)
- then ChunkFull := true ;
- end ;
- until (ChunkFull or Ready) ;
- { close output file; write end-of-file char }
- if not Eof(InFile)
- then BlockWrite (OutFile,EF,1) ;
- Writeln (LineCounter,' lines, ',
- FileSize(OutFile),' bytes written.') ;
- Close (OutFile) ;
- CheckDiskError ;
- Inc (ChunkNr) ;
- end ; { of if }
- end ; { of while }
- Close (InFile) ;
- end.